package br.com.vagacerta.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import br.com.vagacerta.modelo.Cliente;
import br.com.vagacerta.modelo.Email;
import br.com.vagacerta.modelo.PessoaFisica;
import br.com.vagacerta.modelo.PessoaJuridica;
import br.com.vagacerta.modelo.Telefone;

@Repository
public class ClienteDAO {

	private Connection connection;
	private final TelefoneDAO telefoneDAO;
	private final EnderecoDAO enderecoDAO;
	private final EmailDAO emailDAO;
	private final CupomDAO cupomDAO;

	@Autowired
	public ClienteDAO(DataSource dataSource, TelefoneDAO telefoneDAO,
			EnderecoDAO enderecoDAO, EmailDAO emailDAO, CupomDAO cupomDAO) {
		try {
			this.connection = dataSource.getConnection();
			this.telefoneDAO = telefoneDAO;
			this.enderecoDAO = enderecoDAO;
			this.emailDAO = emailDAO;
			this.cupomDAO = cupomDAO;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public List<PessoaFisica> getPessoaFisica(String codigo, String nome,
			String rg, String cpf) {

		try {
			nome = nome == null ? nome : nome.replace("*", "%");
			rg = rg == null ? rg : rg.replace("*", "%");
			cpf = cpf == null ? cpf : cpf.replace("*", "%");
			codigo = codigo == null ? codigo : codigo.replace("*", "%");

			String sql = "select c.COD_CLIENTE, c.COD_TIPO_PESSOA, c.STATUS_CLIENTE, pf.COD_PESSOA_FISICA, pf.NOME,"
					+ "pf.RG, pf.CPF from cliente as c inner join "
					+ "pessoa_fisica as pf on pf.COD_CLIENTE = c.COD_CLIENTE "
					+ "where c.COD_TIPO_PESSOA = 1"
					+ " and ((IF(? = '', null, CAST(? AS UNSIGNED))) is null or c.COD_CLIENTE LIKE (IF (? = '', NULL, CAST(? AS UNSIGNED))))"
					+ " and (? IS NULL OR pf.NOME LIKE ?)"
					+ " and (? is null or pf.RG LIKE ?)"
					+ " and (? is null or pf.CPF LIKE ?)"
					+ " order by pf.NOME ASC";

			PreparedStatement stmt = connection.prepareStatement(sql);

			stmt.setString(1, codigo);
			stmt.setString(2, codigo);
			stmt.setString(3, codigo);
			stmt.setString(4, codigo);
			stmt.setString(5, nome);
			stmt.setString(6, nome);
			stmt.setString(7, rg);
			stmt.setString(8, rg);
			stmt.setString(9, cpf);
			stmt.setString(10, cpf);
			ResultSet rs = stmt.executeQuery();
			List<PessoaFisica> listaPessoaFisica = new ArrayList<PessoaFisica>();

			while (rs.next()) {
				PessoaFisica pf = new PessoaFisica();
				pf.setCodigoCliente(rs.getLong("COD_CLIENTE"));
				pf.setCodigoPessoaFisica(rs.getLong("COD_PESSOA_FISICA"));
				pf.setCodigoTipoPessoa(rs.getInt("COD_TIPO_PESSOA"));
				pf.setNome(rs.getString("NOME"));
				pf.setRg(rs.getString("RG"));
				pf.setCpf(rs.getString("CPF"));
				pf.setStatusCliente(rs.getShort("STATUS_CLIENTE"));
				listaPessoaFisica.add(pf);

			}

			rs.close();
			stmt.close();

			return listaPessoaFisica;

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

	}

	public List<PessoaJuridica> getPessoaJuridica(String codigo,
			String razaoSocial, String cnpj, String im) {

		try {

			razaoSocial = razaoSocial == null ? razaoSocial : razaoSocial
					.replace("*", "%");
			cnpj = cnpj == null ? cnpj : cnpj.replace("*", "%");
			im = im == null ? im : im.replace("*", "%");
			codigo = codigo == null ? codigo : codigo.replace("*", "%");

			String sql = "select c.COD_CLIENTE, c.COD_TIPO_PESSOA, c.STATUS_CLIENTE, pj.COD_PESSOA_JURIDICA, pj.RAZAO_SOCIAL,"
					+ "pj.CNPJ, pj.im from cliente as c inner join "
					+ "pessoa_juridica as pj on pj.COD_CLIENTE = c.COD_CLIENTE "
					+ "where c.COD_TIPO_PESSOA = 2"
					+ " and ((IF(? = '', null, CAST(? AS UNSIGNED))) is null or c.COD_CLIENTE LIKE (IF (? = '', NULL, CAST(? AS UNSIGNED))))"
					+ " and (? IS NULL OR pj.RAZAO_SOCIAL LIKE ?)"
					+ " and (? is null or pj.CNPJ LIKE ?)"
					+ " and (? is null or pj.IM LIKE ?)"
					+ " order by pj.RAZAO_SOCIAL ASC";

			PreparedStatement stmt = connection.prepareStatement(sql);
			stmt.setString(1, codigo);
			stmt.setString(2, codigo);
			stmt.setString(3, codigo);
			stmt.setString(4, codigo);
			stmt.setString(5, razaoSocial);
			stmt.setString(6, razaoSocial);
			stmt.setString(7, cnpj);
			stmt.setString(8, cnpj);
			stmt.setString(9, im);
			stmt.setString(10, im);
			ResultSet rs = stmt.executeQuery();
			List<PessoaJuridica> listaPessoaJuridica = new ArrayList<PessoaJuridica>();

			while (rs.next()) {
				PessoaJuridica pj = new PessoaJuridica();
				pj.setCodigoCliente(rs.getLong("COD_CLIENTE"));
				pj.setCodigoPessoaJuridica(rs.getLong("COD_PESSOA_JURIDICA"));
				pj.setCodigoTipoPessoa(rs.getInt("COD_TIPO_PESSOA"));
				pj.setRazaoSocial(rs.getString("RAZAO_SOCIAL"));
				pj.setCnpj(rs.getString("CNPJ"));
				pj.setIm(rs.getString("IM"));
				pj.setStatusCliente(rs.getShort("STATUS_CLIENTE"));

				listaPessoaJuridica.add(pj);

			}

			rs.close();
			stmt.close();

			return listaPessoaJuridica;

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

	}

	public boolean pesquisaClienteCPF(String CPF) {

		try {

			String sql = "SELECT IF((SELECT count(*) FROM pessoa_fisica WHERE CPF = ?) = 1,'true','false') AS 'EXISTE_CLIENTE_PF'";

			PreparedStatement stmt;
			stmt = connection.prepareStatement(sql);

			stmt.setString(1, CPF);
			ResultSet rs = stmt.executeQuery();
			Boolean existeCliente = false;

			while (rs.next()) {
				existeCliente = Boolean.valueOf(rs
						.getString("EXISTE_CLIENTE_PF"));
			}

			rs.close();
			stmt.close();

			return existeCliente;

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public boolean pesquisaClienteCNPJ(String CNPJ) {

		try {

			String sql = "SELECT IF((SELECT count(*) FROM pessoa_juridica WHERE CNPJ = ?) = 1,'true','false') AS 'EXISTE_CLIENTE_PJ'";

			PreparedStatement stmt;
			stmt = connection.prepareStatement(sql);

			stmt.setString(1, CNPJ);
			ResultSet rs = stmt.executeQuery();
			Boolean existeCliente = false;

			while (rs.next()) {
				existeCliente = Boolean.valueOf(rs
						.getString("EXISTE_CLIENTE_PJ"));
			}

			rs.close();
			stmt.close();

			return existeCliente;

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public void incluiCliente(Cliente pessoa) {

		// INCLUI O NOVO CLIENTE NA TABELA 'CLIENTE'
		pessoa.setCodigoCliente(incluiClienteBD(pessoa.getCodigoTipoPessoa(),
				pessoa.getStatusCliente()));

		// INCLUI A PESSOA FISICA NA TABELA CONFORME O CLIENTE CRIADO (PESSOA
		// FISICA OU JURIDICA)
		if (pessoa.getCodigoTipoPessoa() == 1) {

			PessoaFisica pf = (PessoaFisica) pessoa;
			pf.setCodigoPessoaFisica(incluiPessoaBD(pessoa));
			telefoneDAO.insereTelefoneCliente(pf.getTelefones(),
					pf.getCodigoCliente());
			emailDAO.insereEmailCliente(pf.getEmails(), pf.getCodigoCliente());
			enderecoDAO.insereEnderecoCliente(pf.getEndereco(),
					pf.getCodigoCliente());

		} else if (pessoa.getCodigoTipoPessoa() == 2) {

			PessoaJuridica pj = (PessoaJuridica) pessoa;
			pj.setCodigoPessoaJuridica(incluiPessoaBD(pessoa));
			telefoneDAO.insereTelefoneCliente(pj.getTelefones(),
					pj.getCodigoCliente());
			emailDAO.insereEmailCliente(pj.getEmails(), pj.getCodigoCliente());
			enderecoDAO.insereEnderecoCliente(pj.getEndereco(),
					pj.getCodigoCliente());
		}

	}

	private Long incluiClienteBD(int codigoTipoPessoa, short statusCliente) {
		try {
			String sql = "INSERT INTO CLIENTE (COD_TIPO_PESSOA, STATUS_CLIENTE) VALUES ( ? , ? )";

			PreparedStatement stmt;
			stmt = connection.prepareStatement(sql);

			stmt.setInt(1, codigoTipoPessoa);
			stmt.setShort(2, statusCliente);

			stmt.execute();
			stmt.close();

			String sql2 = "SELECT COD_CLIENTE FROM CLIENTE ORDER BY COD_CLIENTE DESC LIMIT 1";

			PreparedStatement stmt2;
			stmt2 = connection.prepareStatement(sql2);

			ResultSet rs = stmt2.executeQuery();
			Long codCliente = null;

			while (rs.next()) {
				codCliente = rs.getLong("COD_CLIENTE");
			}

			rs.close();
			stmt.close();

			return codCliente;

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	private Long incluiPessoaBD(Cliente tipoPessoa) {
		try {
			Long codTipoCliente = null;

			if (tipoPessoa.getCodigoTipoPessoa() == 1) {

				String sql = "INSERT INTO PESSOA_FISICA (COD_CLIENTE, NOME, RG, CPF) VALUES (?, ?, ?, ?)";

				PessoaFisica pf = (PessoaFisica) tipoPessoa;

				PreparedStatement stmt;
				stmt = connection.prepareStatement(sql);

				stmt.setLong(1, pf.getCodigoCliente());
				stmt.setString(2, pf.getNome());
				stmt.setString(3, pf.getRg());
				stmt.setString(4, pf.getCpf());

				stmt.execute();
				stmt.close();

				String sql2 = "SELECT COD_PESSOA_FISICA FROM PESSOA_FISICA ORDER BY COD_PESSOA_FISICA DESC LIMIT 1";

				PreparedStatement stmt2;
				stmt2 = connection.prepareStatement(sql2);

				ResultSet rs = stmt2.executeQuery();

				while (rs.next()) {
					codTipoCliente = rs.getLong("COD_PESSOA_FISICA");
				}

				rs.close();
				stmt.close();

			} else if (tipoPessoa.getCodigoTipoPessoa() == 2) {

				String sql = "INSERT INTO PESSOA_JURIDICA (COD_CLIENTE, RAZAO_SOCIAL, CNPJ, IM) VALUES (?, ?, ?, ?)";

				PessoaJuridica pj = (PessoaJuridica) tipoPessoa;

				PreparedStatement stmt;
				stmt = connection.prepareStatement(sql);

				stmt.setLong(1, pj.getCodigoCliente());
				stmt.setString(2, pj.getRazaoSocial());
				stmt.setString(3, pj.getCnpj());
				stmt.setString(4, pj.getIm());

				stmt.execute();
				stmt.close();

				String sql2 = "SELECT COD_PESSOA_JURIDICA FROM PESSOA_JURIDICA ORDER BY COD_PESSOA_JURIDICA DESC LIMIT 1";

				PreparedStatement stmt2;
				stmt2 = connection.prepareStatement(sql2);

				ResultSet rs = stmt2.executeQuery();

				while (rs.next()) {
					codTipoCliente = rs.getLong("COD_PESSOA_JURIDICA");
				}

				rs.close();
				stmt.close();

			}

			return codTipoCliente;

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

	}

	public void excluiClientePorId(long idCliente, int tipoPessoa) {

		try {

			if (tipoPessoa == 1) {

				String sql = "DELETE FROM PESSOA_FISICA WHERE COD_CLIENTE = ?";

				PreparedStatement stmt;
				stmt = connection.prepareStatement(sql);

				stmt.setLong(1, idCliente);

				stmt.execute();
				stmt.close();

			} else if (tipoPessoa == 2) {

				String sql = "DELETE FROM PESSOA_JURIDICA WHERE COD_CLIENTE = ?";

				PreparedStatement stmt;
				stmt = connection.prepareStatement(sql);

				stmt.setLong(1, idCliente);

				stmt.execute();
				stmt.close();

			}

			String sql2 = "DELETE FROM CLIENTE WHERE COD_CLIENTE = ?";

			PreparedStatement stmt2;
			stmt2 = connection.prepareStatement(sql2);

			stmt2.setLong(1, idCliente);

			stmt2.execute();
			stmt2.close();

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public Cliente consultaClientePorId(long idCliente) {

		try {
			String sql = "SELECT * FROM CLIENTE WHERE COD_CLIENTE = ? LIMIT 1";

			PreparedStatement stmt;
			stmt = connection.prepareStatement(sql);

			stmt.setLong(1, idCliente);
			ResultSet rs = stmt.executeQuery();
			Cliente cliente = null;

			while (rs.next()) {
				if (rs.getInt("COD_TIPO_PESSOA") == 1) {

					PessoaFisica pf = new PessoaFisica();

					pf.setCodigoCliente(idCliente);
					pf.setCodigoTipoPessoa(rs.getInt("COD_TIPO_PESSOA"));
					pf.setStatusCliente(rs.getShort("STATUS_CLIENTE"));

					cliente = consultaPessoaFisicaporIdCliente(pf);


				} else if (rs.getInt("COD_TIPO_PESSOA") == 2) {

					PessoaJuridica pj = new PessoaJuridica();

					pj.setCodigoCliente(idCliente);
					pj.setCodigoTipoPessoa(rs.getInt("COD_TIPO_PESSOA"));
					pj.setStatusCliente(rs.getShort("STATUS_CLIENTE"));
					
					cliente = consultaPessoaJuridicaporIdCliente(pj);

				}

			}
			
			cliente.setEndereco(enderecoDAO.consultaEnderecoPorIdCliente(idCliente));
			cliente.setEmails(emailDAO.consultaEmailsPorIdCliente(idCliente).toArray(new Email[emailDAO.consultaEmailsPorIdCliente(idCliente).size()]));
			cliente.setTelefones(telefoneDAO.consultaTelefonesPorIdCliente(idCliente).toArray(new Telefone[telefoneDAO.consultaTelefonesPorIdCliente(idCliente).size()]));
			
			
			if(cliente.getStatusCliente() == 1) {
			
				cliente.setCupomMensalista(cupomDAO.retornaCupomMensalistaPorIdCliente(idCliente));
			}
			
			rs.close();
			stmt.close();
			
		return cliente;

		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}

	private PessoaFisica consultaPessoaFisicaporIdCliente(PessoaFisica pf) {
		try {
			
			String sql = "SELECT * FROM PESSOA_FISICA WHERE COD_CLIENTE = ? LIMIT 1";

			PreparedStatement stmt;
			stmt = connection.prepareStatement(sql);

			stmt.setLong(1, pf.getCodigoCliente());
			ResultSet rs = stmt.executeQuery();
			PessoaFisica pfTemp = pf;
			
			while (rs.next()) {
				pfTemp.setCodigoPessoaFisica(rs.getLong("COD_PESSOA_FISICA"));
				pfTemp.setNome(rs.getString("NOME"));
				pfTemp.setCpf(rs.getString("CPF"));
				pfTemp.setRg(rs.getString("RG"));
		}
			
		return pfTemp;
		
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	
	}
	
	private PessoaJuridica consultaPessoaJuridicaporIdCliente(PessoaJuridica pj) {
		try {
			
			String sql = "SELECT * FROM PESSOA_JURIDICA WHERE COD_CLIENTE = ? LIMIT 1";

			PreparedStatement stmt;
			stmt = connection.prepareStatement(sql);

			stmt.setLong(1, pj.getCodigoCliente());
			ResultSet rs = stmt.executeQuery();
			PessoaJuridica pjTemp = pj;
			
			while (rs.next()) {
				pjTemp.setCodigoPessoaJuridica(rs.getLong("COD_PESSOA_JURIDICA"));
				pjTemp.setRazaoSocial(rs.getString("RAZAO_SOCIAL"));
				pjTemp.setCnpj(rs.getString("CNPJ"));
				pjTemp.setIm(rs.getString("IM"));
		}
			
		return pjTemp;
		
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	
	}

	public void ativaClientePorId(long idCliente) throws SQLException {
			
			String sql = "UPDATE CLIENTE SET STATUS_CLIENTE = 1 WHERE COD_CLIENTE = ?";

			PreparedStatement stmt;
			stmt = connection.prepareStatement(sql);

			stmt.setLong(1, idCliente);

			stmt.execute();
			stmt.close();

		
	}
}
